pull code: support contenturl setting
authorJonathan Lebon <jlebon@redhat.com>
Thu, 11 Aug 2016 20:01:27 +0000 (16:01 -0400)
committerAtomic Bot <atomic-devel@projectatomic.io>
Wed, 31 Aug 2016 16:52:12 +0000 (16:52 +0000)
Allow users to pass a --contenturl during `remote add` and store it in
the remote config.

Fish out the contenturl setting from the remote config and use it when
downloading static deltas and objects (except for commit signatures).
The idea here is that items in the trust chain (summary & sigs) can be
fetched from a more secure e.g. TLS-pinned location, while objects
themselves are fetched from another location. Once mirrorlist support is
added, this use-case will become even more advantageous.

Closes: #469
Approved by: cgwalters

src/libostree/ostree-repo-pull.c
src/ostree/ot-remote-builtin-add.c

index ed1c67ef27b1a015f903d08b74777c6995e1c795..8589d716f815b1ccb0e5491a8d25f6cfad7cabe3 100644 (file)
@@ -47,6 +47,7 @@ typedef struct {
   OstreeRepoMode remote_mode;
   OstreeFetcher *fetcher;
   SoupURI      *base_uri;
+  SoupURI      *base_content_uri;
   OstreeRepo   *remote_repo_local;
 
   GMainContext    *main_context;
@@ -1347,7 +1348,7 @@ enqueue_one_object_request (OtPullData        *pull_data,
   else
     {
       objpath = _ostree_get_relative_object_path (checksum, objtype, TRUE);
-      obj_uri = suburi_new (pull_data->base_uri, objpath, NULL);
+      obj_uri = suburi_new (pull_data->base_content_uri, objpath, NULL);
     }
 
   is_meta = OSTREE_OBJECT_TYPE_IS_META (objtype);
@@ -1431,7 +1432,7 @@ request_static_delta_superblock_sync (OtPullData  *pull_data,
   g_autoptr(GVariant) delta_superblock = NULL;
   SoupURI *target_uri = NULL;
   
-  target_uri = suburi_new (pull_data->base_uri, delta_name, NULL);
+  target_uri = suburi_new (pull_data->base_content_uri, delta_name, NULL);
   
   if (!fetch_uri_contents_membuf_sync (pull_data, target_uri, FALSE, TRUE,
                                        &delta_superblock_data,
@@ -1734,7 +1735,7 @@ process_one_static_delta (OtPullData   *pull_data,
         }
       else
         {
-          target_uri = suburi_new (pull_data->base_uri, deltapart_path, NULL);
+          target_uri = suburi_new (pull_data->base_content_uri, deltapart_path, NULL);
           _ostree_fetcher_request_uri_with_partial_async (pull_data->fetcher, target_uri, size,
                                                           OSTREE_FETCHER_DEFAULT_PRIORITY,
                                                           pull_data->cancellable,
@@ -2382,6 +2383,30 @@ ostree_repo_pull_with_options (OstreeRepo             *self,
                                                      summary_bytes, FALSE);
     }
 
+  {
+    g_autofree char *contenturl = NULL;
+
+    if (metalink_url_str == NULL && url_override != NULL)
+      contenturl = g_strdup (url_override);
+    else if (!ostree_repo_get_remote_option (self, remote_name_or_baseurl,
+                                             "contenturl", NULL,
+                                             &contenturl, error))
+      goto out;
+
+    if (contenturl == NULL)
+      pull_data->base_content_uri = soup_uri_copy (pull_data->base_uri);
+    else
+      {
+        pull_data->base_content_uri = soup_uri_new (contenturl);
+        if (!pull_data->base_content_uri)
+          {
+            g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                         "Failed to parse contenturl '%s'", contenturl);
+            goto out;
+          }
+      }
+  }
+
   if (!ostree_repo_get_remote_list_option (self,
                                            remote_name_or_baseurl, "branches",
                                            &configured_branches, error))
@@ -2901,6 +2926,8 @@ ostree_repo_pull_with_options (OstreeRepo             *self,
   g_free (pull_data->remote_name);
   if (pull_data->base_uri)
     soup_uri_free (pull_data->base_uri);
+  if (pull_data->base_content_uri)
+    soup_uri_free (pull_data->base_content_uri);
   g_clear_pointer (&pull_data->summary_data, (GDestroyNotify) g_bytes_unref);
   g_clear_pointer (&pull_data->summary_data_sig, (GDestroyNotify) g_bytes_unref);
   g_clear_pointer (&pull_data->summary, (GDestroyNotify) g_variant_unref);
index 461d9099dc46206f64d3b51c42116ce28bd8ad55..4e1d5595dfd9a51c50a0998ef0295eca746edf29 100644 (file)
@@ -30,12 +30,14 @@ static char **opt_set;
 static gboolean opt_no_gpg_verify;
 static gboolean opt_if_not_exists;
 static char *opt_gpg_import;
+static char *opt_contenturl;
 
 static GOptionEntry option_entries[] = {
   { "set", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_set, "Set config option KEY=VALUE for remote", "KEY=VALUE" },
   { "no-gpg-verify", 0, 0, G_OPTION_ARG_NONE, &opt_no_gpg_verify, "Disable GPG verification", NULL },
   { "if-not-exists", 0, 0, G_OPTION_ARG_NONE, &opt_if_not_exists, "Do nothing if the provided remote exists", NULL },
   { "gpg-import", 0, 0, G_OPTION_ARG_FILENAME, &opt_gpg_import, "Import GPG key from FILE", "FILE" },
+  { "contenturl", 0, 0, G_OPTION_ARG_STRING, &opt_contenturl, "Use URL when fetching content", "URL" },
   { NULL }
 };
 
@@ -83,6 +85,14 @@ ot_remote_builtin_add (int argc, char **argv, GCancellable *cancellable, GError
                              g_variant_new_variant (g_variant_new_strv ((const char*const*)branchesp->pdata, -1)));
     }
 
+  /* We could just make users use --set instead for this since it's a string,
+   * but e.g. when mirrorlist support is added, it'll be kinda awkward to type:
+   *   --set=contenturl=mirrorlist=... */
+
+  if (opt_contenturl != NULL)
+    g_variant_builder_add (optbuilder, "{s@v}",
+                           "contenturl", g_variant_new_variant (g_variant_new_string (opt_contenturl)));
+
   for (iter = opt_set; iter && *iter; iter++)
     {
       const char *keyvalue = *iter;